package es.uc3m.setichat.utils;

import java.util.ArrayList;

import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.KeyFactory;
import com.google.appengine.api.datastore.PreparedQuery;
import com.google.appengine.api.datastore.Query;
import com.google.appengine.api.datastore.Text;

import es.uc3m.setichat.appengine.servlets.CreateSetiChatMessageException;
import es.uc3m.setichat.appengine.servlets.XmppReceiverServlet;
import es.uc3m.setichat.constants.DataModelConstants;
import es.uc3m.setichat.constants.GeneralConstants;
import es.uc3m.setichat.constants.MessageTypeConstants;
import es.uc3m.setichat.constants.TypeCertificationConstants;
import es.uc3m.setichat.utils.setichatxmlschema.SetiChatMessage;
import es.uc3m.setichat.utils.setichatxmlschema.SetiChatMessageFactory;

public class SecurityManager {
	public static void broadcastRevocation(String numberRevocation) {
		ArrayList<String> listToRevoke = getListToRevocate(numberRevocation);
		String scXmlRevocation = new String();
		SetiChatMessage scMsgRevocation = null;
		for (String numDstRev : listToRevoke) {
			SetiChatMessageFactory scMessageRevocation = new SetiChatMessageFactory();
			scXmlRevocation = scMessageRevocation
					.createSetiChatMessageRevocation(
							GeneralConstants.SELF,
							numDstRev,
							ServerActions.generateRandomID(),
							String.valueOf(MessageTypeConstants.TYPE_REVOCATION),
							false, false, numberRevocation);
			try {
				scMsgRevocation = XmppReceiverServlet.setiChatMessageFactory
						.createSetiChatMessage(scXmlRevocation);
				ServerActions.sendToMessage(scMsgRevocation);
			} catch (CreateSetiChatMessageException e) {
				XmppReceiverServlet.log.warning("Error revocation message");
			}
		}

	}

	private static ArrayList<String> getListToRevocate(String mobileRevocation) {
		ArrayList<String> listToRevocate = new ArrayList<String>();
		Query queryRevocation = new Query(DataModelConstants.DS_ENTITY_CONTACTS);
		Key k = KeyFactory.createKey(DataModelConstants.DS_ENTITY_CONTACTS,
				mobileRevocation);
		queryRevocation.setAncestor(k);
		PreparedQuery pq = XmppReceiverServlet.datastore
				.prepare(queryRevocation);
		for (Entity result : pq.asIterable()) {
			long numContacts = (Long) result
					.getProperty(DataModelConstants.DS_PROPERTY_CONTACTS_NUMCONTACTS);

			for (int i = 0; i <= numContacts; i++) {
				String numDstRev = (String) result
						.getProperty(DataModelConstants.DS_PROPERTY_CONTACTS_CONTACTX
								+ i);
				listToRevocate.add(numDstRev);
			}
		}
		return listToRevocate;
	}

	public static String getCertification(String user, String type) {
		String cert = new String();
		if (type.equalsIgnoreCase(TypeCertificationConstants.TYPE_CERT_CER)) {
			cert = getPublicCert(user);
		} else if (type
				.equalsIgnoreCase(TypeCertificationConstants.TYPE_CERT_P12)) {
			cert = getPrivateCert(user);
		}
		return cert;
	}

	private static String getPrivateCert(String user) {
		Query queryCert = new Query(DataModelConstants.DS_ENTITY_CERTIFICATE);
		Key k = KeyFactory.createKey(DataModelConstants.DS_ENTITY_CERTIFICATE,
				user);
		queryCert.setAncestor(k);
		PreparedQuery pq = XmppReceiverServlet.datastore.prepare(queryCert);
		Text p12 = null;
		for (Entity result : pq.asIterable()) {
			p12 = (Text) (result
					.getProperty(DataModelConstants.DS_PROPERTY_CERTIFICATE_PRIVATE_KEY));
		}
		String certificate = new String();
		if (p12 != null) {
			certificate = p12.getValue();
		}
		return certificate;
	}

	private static String getPublicCert(String user) {
		Query queryCert = new Query(DataModelConstants.DS_ENTITY_CERTIFICATE);
		Key k = KeyFactory.createKey(DataModelConstants.DS_ENTITY_CERTIFICATE,
				user);
		queryCert.setAncestor(k);
		PreparedQuery pq = XmppReceiverServlet.datastore.prepare(queryCert);
		Text cer = null;
		for (Entity result : pq.asIterable()) {
			cer = (Text) (result
					.getProperty(DataModelConstants.DS_PROPERTY_CERTIFICATE_PUBLIC_KEY));
		}
		String certificate = new String();
		if (cer != null) {
			certificate = cer.getValue();
		}
		return certificate;
	}

	public static boolean hasCertificate(String user, String type) {
		boolean hasCertificate = false;
		Query queryCert = new Query(DataModelConstants.DS_ENTITY_CERTIFICATE);
		Key k = KeyFactory.createKey(DataModelConstants.DS_ENTITY_CERTIFICATE,
				user);
		queryCert.setAncestor(k);
		PreparedQuery pq = XmppReceiverServlet.datastore.prepare(queryCert);
		Object cer = null;
		for (Entity result : pq.asIterable()) {
			if (type.equalsIgnoreCase(TypeCertificationConstants.TYPE_CERT_CER)) {
				cer = result
						.getProperty(DataModelConstants.DS_PROPERTY_CERTIFICATE_PUBLIC_KEY);
			} else if (type
					.equalsIgnoreCase(TypeCertificationConstants.TYPE_CERT_P12)) {
				cer = result
						.getProperty(DataModelConstants.DS_PROPERTY_CERTIFICATE_PRIVATE_KEY);
			}
			if (cer != null) {
				hasCertificate = true;
			}
		}

		return hasCertificate;
	}

	public static void putCertificate(String user, String type, String cert) {
		Entity certificate = new Entity(
				DataModelConstants.DS_ENTITY_CERTIFICATE, user);
		if (type.equalsIgnoreCase(TypeCertificationConstants.TYPE_CERT_CER)) {
			Text txtCert = new Text(cert);
			certificate.setProperty(
					DataModelConstants.DS_PROPERTY_CERTIFICATE_PUBLIC_KEY,
					txtCert);
			if (hasCertificate(user, TypeCertificationConstants.TYPE_CERT_P12)) {
				String certPrivado = getPrivateCert(user);
				Text txtCertPriv = new Text(certPrivado);
				certificate.setProperty(
						DataModelConstants.DS_PROPERTY_CERTIFICATE_PRIVATE_KEY,
						txtCertPriv);
			}

		} else if (type
				.equalsIgnoreCase(TypeCertificationConstants.TYPE_CERT_P12)) {
			Text txtCert = new Text(cert);
			certificate.setProperty(
					DataModelConstants.DS_PROPERTY_CERTIFICATE_PRIVATE_KEY,
					txtCert);
			if (hasCertificate(user, TypeCertificationConstants.TYPE_CERT_CER)) {
				String certPublico = getPublicCert(user);
				Text txtCertPubli = new Text(certPublico);
				certificate.setProperty(
						DataModelConstants.DS_PROPERTY_CERTIFICATE_PUBLIC_KEY,
						txtCertPubli);
			}
		}
		XmppReceiverServlet.datastore.put(certificate);
	}

}
